package com.xayy.mgt.service.impl;

import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.TimedCache;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xayy.core.constant.ConfigCalPath;
import com.xayy.mgt.enums.XzHealthStatus;
import com.xayy.mgt.model.vo.GenerateTheoryDataVo;
import com.xayy.mgt.model.xinwangmodel.AssessHistory;
import com.xayy.mgt.model.xinwangmodel.HealthEntity;
import com.xayy.mgt.model.xinwangmodel.SateLinkData;
import com.xayy.mgt.service.AssessHistoryService;
import com.xayy.mgt.service.GenerateTheoryDataAsyncService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.*;

/**
 * 生成理论数据异步请求
 * @author plq
 */
@Service
@Slf4j
public class GenerateTheoryDataAsyncServiceImpl implements GenerateTheoryDataAsyncService {

    @Autowired
    private ConfigCalPath configCalPath;

    @Autowired
    private SimpMessagingTemplate messagingTemplate;

    @Autowired
    private AssessHistoryService assessHistoryService;



    /**
     * 定时缓存
     */
    public static TimedCache<String, Object> cache = CacheUtil.newTimedCache(600000);

    static {
        cache.schedulePrune(600000);
    }


    @Override
    public String requestUploadFile(String filePath, String localFilePath) {
        String adminToken = getAdminToken().get("token").toString();
        if(adminToken == null){
            return null;
        }
        HttpResponse execute = HttpRequest.post(configCalPath.getReUrl() + "/jeecg-boot/sys/common/upload")
                .header("X-Access-Token", adminToken)
                .form("file",new File(localFilePath))
                .form("biz",filePath)
                .execute();
        JSONObject jsonObject = JSONObject.parseObject(execute.body());
        if(Boolean.parseBoolean(jsonObject.get("success").toString())){
            return jsonObject.get("message").toString();
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    @Override
    public Map<String,Object> getAdminToken() {
        if(cache.get("adminInfo") != null){
            Map<String, Object> adminInfo = (Map<String, Object>)cache.get("adminInfo");
            log.info("获取缓存的管理员信息：，管理员id：{}，token:{}",adminInfo.get("userId"),adminInfo.get("token"));
            return adminInfo;
        }
        /*远程登录获取token,由于这个获取用户token的接口是不是会报错，不保证头一次会成功，因此循环延迟调用比较保守，直到token获取成功或者次数用完,默认给10次*/
        Map<String,Object> map = new HashMap<>(2);
        try {
            int max =10;
            for (int i = 1; i<= max; i++){
                log.info("获取Token地址：{}",configCalPath.getReUrl()+"/jeecg-boot/sys/public/login");
                String reStr = HttpUtil.get(configCalPath.getReUrl()+"/jeecg-boot/sys/public/login");
                JSONObject jsonObject = JSONObject.parseObject(reStr);
                if(!"200".equals(jsonObject.get("code").toString())){
                    log.error("远程调用:\"{}\"。获取管理员token接口失败："+jsonObject.get("message").toString(),configCalPath.getReUrl()+"/jeecg-boot/sys/public/login");
                }else{
                    JSONObject result = (JSONObject)jsonObject.get("result");
                    JSONObject userInfo = (JSONObject)result.get("userInfo");
                    map.put("token", result.get("token").toString());
                    map.put("userId", userInfo.get("id").toString());
                    log.info("获取管理员token：次数：{}，管理员id：{}，token:{}",i,map.get("userId"),map.get("token"));
                    cache.put("adminInfo",map);
                    break;
                }
                Thread.sleep(3000);
            }
        } catch (InterruptedException e) {
            log.error("远程调用:\"{}\"。获取管理员token接口失败："+e.getMessage(),configCalPath.getReUrl()+"/jeecg-boot/sys/public/login");
        }
        if(map.isEmpty()){
            return null;
        }
        return map;
    }

    @Override
    public void generateTheoryData(GenerateTheoryDataVo build) {
        /*远程调用生成理论数据*/
        String adminToken = getAdminToken().get("token").toString();
        try {
            HttpResponse execute = HttpRequest.post(configCalPath.getReUrl() + "/jeecg-boot/topology/newUploadSateLite")
                    .header("X-Access-Token", adminToken)
                    .body(JSON.toJSONString(build))
                    .execute();
            log.error("远程调用生成理论数据成功:"+execute.body());
            messagingTemplate.convertAndSend("/topic/sub/generateTheoryData", execute.body());
        } catch (Exception e) {
            log.error("远程调用生成理论数据失败:"+e.getMessage());
        }
    }

    @Override
    public void healthAsyncAssess(HealthEntity healthEntity, String adminToken,List<SateLinkData> data) {
        /*请求参数拼接*/
        Map<String,Object> fault = new HashMap<>();
        List<Map<String,Object>> list = new ArrayList<>();
        /*获取真实数据，做健康评估*/
        data.forEach(item ->{
            Map<String,Object> dataMap = new HashMap<>();
            dataMap.put("type","edge");
            String source = item.getSatelliteCode1().replaceAll("[a-zA-Z]", "");
            String dest = item.getSatelliteCode2().replaceAll("[a-zA-Z]", "");
            dataMap.put("source",source);
            dataMap.put("dest",dest);
            dataMap.put("rate",item.getSateRateRealityValue());
            list.add(dataMap);
        });
        fault.put("fault",list);
        Map<String,Object> select = new HashMap<>(1);
        select.put("Algselect",1);
        Map<String,Object> requestMap = new HashMap<>();
        requestMap.put("fault",JSON.toJSONString(fault));
        requestMap.put("select",JSON.toJSONString(select));
        requestMap.put("algorithmType",healthEntity.getAlgorithmType());
        AssessHistory assessHistory=AssessHistory.builder().assessTime(new Date()).build();
        try {
            HttpResponse execute = HttpRequest.post(configCalPath.getReUrl() + "/jeecg-boot/topology/networkHealth")
                    .header("X-Access-Token", adminToken)
                    .body(JSON.toJSONString(requestMap))
                    .timeout(500000)
                    .execute();
            log.info("健康评估完成，评估结果数据：{}",execute.body());
            JSONObject jsonObject = JSONObject.parseObject(execute.body());
            if(null != jsonObject.get("code") && "200".equals(jsonObject.get("code"))){
                if(jsonObject.get("result") != null){
                    jsonObject.put("level", XzHealthStatus.valueOf(Double.parseDouble(jsonObject.get("result").toString())));
                    assessHistory.setLevel(XzHealthStatus.valueOf(Double.parseDouble(jsonObject.get("result").toString())));
                    assessHistory.setScore(Double.parseDouble(jsonObject.get("result").toString()));
                }else{
                    jsonObject.put("level", "评估结果错误");
                    assessHistory.setLevel("评估结果错误");
                    assessHistory.setScore(null);
                    log.error("健康评估result 错误，评估结果数据：{}",execute.body());
                }
            }else{
                jsonObject.put("level", "请求错误");
                assessHistory.setLevel("评估请求错误");
                assessHistory.setScore(null);
                log.error("健康评估失败，评估结果数据：{}",execute.body());
            }
            messagingTemplate.convertAndSend("/topic/sub/healthAsyncAssess", jsonObject);

        } catch (Exception e) {
            assessHistory.setLevel("评估超时");
            assessHistory.setScore(null);
            Map<String,Object> returnMap = new HashMap<>();
            returnMap.put("code",1000);
            returnMap.put("message","评估超时");
            log.info("健康评估超时");
            messagingTemplate.convertAndSend("/topic/sub/healthAsyncAssess", returnMap);
        }
        int insert = assessHistoryService.insert(assessHistory);
        if(insert > 0){
            log.info("健康评估入库结果：{}",assessHistory.toString());
        }

    }

}
